package cn.yx.framework.security;

import cn.yx.framework.util.HexUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class MD5Util {
    private static final Logger logger = LoggerFactory.getLogger(MD5Util.class);

    /**
     * 默认的密码字符串组合，apache校验下载的文件的正确性用的就是默认的此组合
     */
    protected static char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    protected static MessageDigest messagedigest = null;

    public MD5Util() {
    }

    static {
        try {
            messagedigest = MessageDigest.getInstance("MD5");

        } catch (NoSuchAlgorithmException nsaex) {
            System.err.println(MD5Util.class.getName() + "初始化失败，MessageDigest不支持MD5Util。");
            nsaex.printStackTrace();
        }
    }

    public static String md5Str(String str) {
        byte[] bytes = null;

        try {
            messagedigest = MessageDigest.getInstance("MD5");
            MessageDigest e = MessageDigest.getInstance("MD5");
            bytes = e.digest(str.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException var3) {
            logger.error("unsupported encoding or no such algorithm exception", var3);
        }

        return HexUtil.bytes2HexStr(bytes, false);
    }

    public static String md5Str(String str, String salt) {
        List resp = Arrays.asList(new String[]{md5Str(str), salt});
        resp.sort(Comparator.naturalOrder());
        return md5Str(((String) resp.get(0)).concat((String) resp.get(1)));
    }

    public static String md5File(File file) {
        String ret = "";
        FileInputStream in = null;
        FileChannel ch = null;

        try {
            in = new FileInputStream(file);
            ch = in.getChannel();
            MappedByteBuffer e = ch.map(MapMode.READ_ONLY, 0L, file.length());
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(e);
            ret = HexUtil.bytes2HexStr(md5.digest());
        } catch (NoSuchAlgorithmException | IOException var18) {
            logger.error("unsupported encoding or no such algorithm exception", var18);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException var17) {
                    var17.printStackTrace();
                }
            }

            if (ch != null) {
                try {
                    ch.close();
                } catch (IOException var16) {
                    var16.printStackTrace();
                }
            }

        }

        return ret;
    }

    private static String bufferToHex(byte bytes[]) {
        return bufferToHex(bytes, 0, bytes.length);
    }

    private static String bufferToHex(byte bytes[], int m, int n) {
        StringBuffer stringbuffer = new StringBuffer(2 * n);
        int k = m + n;
        for (int l = m; l < k; l++) {
            appendHexPair(bytes[l], stringbuffer);
        }
        return stringbuffer.toString();
    }

    private static void appendHexPair(byte bt, StringBuffer stringbuffer) {
        char c0 = hexDigits[(bt & 0xf0) >> 4];
        char c1 = hexDigits[bt & 0xf];
        stringbuffer.append(c0);
        stringbuffer.append(c1);
    }

    public static String getMD5String(String s)  {
        return getMD5String(s.getBytes());
    }

    public static String getMD5String(byte[] bytes) {

        messagedigest.update(bytes);
        return bufferToHex(messagedigest.digest());
    }

    public static boolean checksum(File file, String md5) {
        return md5File(file).equalsIgnoreCase(md5);
    }

    public static boolean checksum(String str, String md5) {
        return md5Str(str).equalsIgnoreCase(md5);
    }

    public static void main(String args[]) {
        System.out.println(Charset.defaultCharset().toString());
        System.out.println(getMD5String("Cs28riQQj4t9evffoNdevicdId192.168.100.1ownerOrgIdORGtjfj5RxYOBv2aJ3dKYrepairEndTime2017-08-12 17:20:46"));
    }
}

